home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / nslookup / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-27  |  24.6 KB  |  946 lines

  1. /*
  2.  * Copyright (c) 1985 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. char copyright[] =
  20. "@(#) Copyright (c) 1985 Regents of the University of California.\n\
  21.  All rights reserved.\n";
  22. #endif /* not lint */
  23.  
  24. #ifndef lint
  25. static char sccsid[] = "@(#)main.c    5.20 (Berkeley) 7/24/88";
  26. #endif /* not lint */
  27.  
  28. /*
  29.  *******************************************************************************
  30.  *  
  31.  *   main.c --
  32.  *  
  33.  *      Main routine and some action routines for the name server
  34.  *    lookup program.
  35.  *
  36.  *      Andrew Cherenson     
  37.  *    U.C. Berkeley Computer Science Div.
  38.  *    CS298-26, Fall 1985
  39.  *  
  40.  *******************************************************************************
  41.  */
  42.  
  43. #include <stdio.h>
  44. #include <strings.h>
  45. #include <sys/param.h>
  46. #include <netdb.h>
  47. #include <sys/socket.h>
  48. #include <netinet/in.h>
  49. #include <arpa/nameser.h>
  50. #include <resolv.h>
  51. #include <signal.h>
  52. #include <setjmp.h>
  53. #include <ctype.h>
  54. #include "res.h"
  55.  
  56. /*
  57.  *  Location of the help file.
  58.  */
  59.  
  60. #ifndef HELPFILE
  61. #define HELPFILE "/usr/local/nslookup.help"
  62. #endif
  63.  
  64.  
  65. /*
  66.  *  Default Internet address of the current host.
  67.  */
  68.  
  69. #if BSD < 43
  70. #define LOCALHOST "127.0.0.1"
  71. #endif
  72.  
  73.  
  74. /*
  75.  * Name of a top-level name server. Can be changed with 
  76.  * the "set root" command.
  77.  */
  78.  
  79. #ifndef ROOT_SERVER
  80. #define        ROOT_SERVER "sri-nic.arpa."
  81. #endif
  82. char         rootServerName[NAME_LEN];
  83.  
  84.  
  85. /*
  86.  *  Import the state information from the resolver library.
  87.  */
  88.  
  89. extern struct state _res;
  90.  
  91.  
  92. /*
  93.  *  Info about the most recently queried host.
  94.  */
  95.  
  96. HostInfo    curHostInfo;
  97. int        curHostValid = FALSE;
  98.  
  99.  
  100. /*
  101.  *  Info about the default name server.
  102.  */
  103.  
  104. HostInfo     *defaultPtr = NULL;
  105. char         defaultServer[NAME_LEN];
  106. struct in_addr    defaultAddr;
  107.  
  108.  
  109. /*
  110.  *  Initial name server query type is Address.
  111.  */
  112.  
  113. int         queryType = T_A;
  114. int         queryClass = C_IN;
  115.  
  116. /*
  117.  * Stuff for Interrupt (control-C) signal handler.
  118.  *  SockFD is the file descriptor for sockets used to
  119.  *  connect with the name servers. It has to be global to
  120.  *  allow the interrupt handler can close open sockets.
  121.  */
  122.  
  123. extern int     IntrHandler();
  124. int         sockFD = -1;
  125. FILE         *filePtr;
  126. jmp_buf     env;
  127.  
  128.  
  129.  
  130. /*
  131.  *******************************************************************************
  132.  *
  133.  *  main --
  134.  *
  135.  *    Initializes the resolver library and determines the address
  136.  *    of the initial name server. The yylex routine is used to
  137.  *    read and perform commands.
  138.  *
  139.  *******************************************************************************
  140.  */
  141.  
  142. main(argc, argv)
  143.     int        argc;
  144.     char    **argv;
  145. {
  146.     char    *wantedHost = NULL;
  147.     Boolean    useLocalServer;
  148.     int     result;
  149.     int        i;
  150.     struct hostent    *hp;
  151.     extern int    h_errno;
  152.  
  153.     /*
  154.      *  Initialize the resolver library routines.
  155.      */
  156.  
  157.     if (res_init() == -1) {
  158.     fprintf(stderr,"*** Can't initialize resolver.\n");
  159.     exit(1);
  160.     }
  161.  
  162.     /*
  163.      *  Allocate space for the default server's host info and
  164.      *  find the server's address and name. If the resolver library
  165.      *  already has some addresses for a potential name server,
  166.      *  then use them. Otherwise, see if the current host has a server.
  167.      *  Command line arguments may override the choice of initial server. 
  168.      */
  169.  
  170.     defaultPtr = (HostInfo *) Calloc(1, sizeof(HostInfo));
  171.  
  172.     /*
  173.      * Parse the arguments:
  174.      *  no args =  go into interactive mode, use default host as server
  175.      *    1 arg    =  use as host name to be looked up, default host will be server
  176.      *           non-interactive mode
  177.      *  2 args    =  1st arg: 
  178.      *             if it is '-', then 
  179.      *                ignore but go into interactive mode
  180.      *              else 
  181.      *                 use as host name to be looked up, 
  182.      *             go into non-interactive mode
  183.      *         2nd arg: name or inet address of server
  184.      *
  185.      *    "Set" options are specified with a leading - and must come before
  186.      *    any arguments. For example, to find the well-known services for
  187.      *  a host, type "nslookup -query=wks host"
  188.      */
  189.  
  190.     ++argv; --argc;        /* skip prog name */
  191.  
  192.     while (argc && *argv[0] == '-' && argv[0][1]) {
  193.     (void) SetOption (&(argv[0][1]));
  194.     ++argv; --argc;
  195.     }
  196.     if (argc > 2) {
  197.     Usage();
  198.     } 
  199.     if (argc && *argv[0] != '-') {
  200.     wantedHost = *argv;    /* name of host to be looked up */
  201.     }
  202.  
  203.     useLocalServer = FALSE;
  204.     if (argc == 2) {
  205.  
  206.     /*
  207.      *    Set explicit name server address.
  208.      */ 
  209.  
  210.     _res.nscount = 1;
  211.     _res.nsaddr.sin_addr.s_addr = inet_addr(*++argv);
  212.     if (_res.nsaddr.sin_addr.s_addr == (unsigned)-1) {
  213.         hp = gethostbyname(*argv);
  214.         if (hp == NULL){
  215.         herror(*argv);
  216.         _res.nscount = 0;
  217.         useLocalServer = TRUE;
  218.         } else {
  219. #if BSD >= 43
  220.         bcopy(hp->h_addr_list[0], &_res.nsaddr.sin_addr, hp->h_length);
  221. #else
  222.         bcopy(hp->h_addr, &_res.nsaddr.sin_addr, hp->h_length);
  223. #endif
  224.         } 
  225.     }
  226.     }
  227.  
  228.  
  229.     if (_res.nscount == 0 || useLocalServer) {
  230.     LocalServer(defaultPtr);
  231.     } else {
  232.     for (i = 0; i < _res.nscount; i++) {
  233.         if (_res.nsaddr_list[i].sin_addr.s_addr == INADDR_ANY) {
  234.             LocalServer(defaultPtr);
  235.         break;
  236.         } else {
  237.         result = FindHostInfo(&(_res.nsaddr_list[i].sin_addr), 
  238.                     &(_res.nsaddr_list[i].sin_addr), 
  239.                     sizeof(struct in_addr),
  240.                     defaultPtr);
  241.         if (result != SUCCESS) {
  242.             fprintf(stderr,
  243.             "*** Can't find server name for address %s: %s\n", 
  244.                inet_ntoa(_res.nsaddr_list[i].sin_addr), 
  245.                DecodeError(result));
  246.         } else {
  247.             defaultAddr = _res.nsaddr_list[i].sin_addr;
  248.             break;
  249.         }
  250.         }
  251.     }
  252.  
  253.     /*
  254.      *  If we have exhausted the list, tell the user about the
  255.      *  command line argument to specify an address.
  256.      */
  257.  
  258.     if (i == _res.nscount) {
  259.         fprintf(stderr, 
  260.         "*** Default servers are not available\n");
  261.         exit(1);
  262.     }
  263.  
  264.     }
  265.     strcpy(defaultServer, defaultPtr->name);
  266.     strcpy(rootServerName, ROOT_SERVER);
  267.  
  268.  
  269. #ifdef DEBUG
  270. #ifdef DEBUG2
  271.     _res.options |= RES_DEBUG2;
  272. #endif
  273.     _res.options |= RES_DEBUG;
  274.     _res.retry    = 2;
  275. #endif DEBUG
  276.  
  277.     /*
  278.      * If we're in non-interactive mode, look up the wanted host and quit.
  279.      * Otherwise, print the initial server's name and continue with
  280.      * the initialization.
  281.      */
  282.  
  283.     if (wantedHost != (char *) NULL) {
  284.     LookupHost(wantedHost, 0);
  285.     } else {
  286.     PrintHostInfo(stdout, "Default Server:", defaultPtr);
  287.  
  288.     /*
  289.      * Setup the environment to allow the interrupt handler to return here.
  290.      */
  291.  
  292.     (void) setjmp(env);
  293.  
  294.     /* 
  295.      * Return here after a longjmp.
  296.      */
  297.  
  298.     signal(SIGINT, IntrHandler);
  299.     signal(SIGPIPE, SIG_IGN);
  300.  
  301.     /*
  302.      * Read and evaluate commands. The commands are described in commands.l
  303.      * Yylex returns 0 when ^D or 'exit' is typed. 
  304.      */
  305.  
  306.     printf("> ");
  307.     while(yylex()) {
  308.         printf("> ");
  309.     }
  310.     }
  311.     exit(0);
  312. }
  313.  
  314.  
  315. LocalServer(defaultPtr)
  316.     HostInfo *defaultPtr;
  317. {
  318.     char    hostName[NAME_LEN];
  319.     int result;
  320.  
  321.     gethostname(hostName, sizeof(hostName));
  322.  
  323. #if BSD >= 43
  324.     defaultAddr.s_addr = htonl(INADDR_ANY);
  325.     (void) GetHostInfo(&defaultAddr, C_IN, T_A, "0.0.0.0", defaultPtr, 1);
  326.     free(defaultPtr->name);
  327.     defaultPtr->name = Calloc(1, sizeof(hostName)+1);
  328.     strcpy(defaultPtr->name, hostName);
  329. #else
  330.  
  331.     defaultAddr.s_addr = inet_addr(LOCALHOST);
  332.     result = GetHostInfo(&defaultAddr, C_IN, T_A, hostName, defaultPtr, 1);
  333.     if (result != SUCCESS) {
  334.     fprintf(stderr,
  335.     "*** Can't find initialize address for server %s: %s\n",
  336.             defaultServer, DecodeError(result));
  337.     exit(1);
  338.     }
  339. #endif
  340. }
  341.  
  342.  
  343. /*
  344.  *******************************************************************************
  345.  *
  346.  *  Usage --
  347.  *
  348.  *    Lists the proper methods to run the program and exits.
  349.  *
  350.  *******************************************************************************
  351.  */
  352.  
  353. Usage()
  354. {
  355.     fprintf(stderr, "Usage:\n");
  356.     fprintf(stderr,
  357. "   nslookup [-opt ...]             # interactive mode using default server\n");
  358.     fprintf(stderr,
  359. "   nslookup [-opt ...] - server    # interactive mode using 'server'\n");
  360.     fprintf(stderr,
  361. "   nslookup [-opt ...] host        # just look up 'host' using default server\n");
  362.     fprintf(stderr,
  363. "   nslookup [-opt ...] host server # just look up 'host' using 'server'\n");
  364.     exit(1);
  365. }
  366.  
  367.  
  368. /*
  369.  *******************************************************************************
  370.  *
  371.  *  SetDefaultServer --
  372.  *
  373.  *    Changes the default name server to the one specified by
  374.  *    the first argument. The command "server name" uses the current 
  375.  *    default server to lookup the info for "name". The command
  376.  *    "lserver name" uses the original server to lookup "name".
  377.  *
  378.  *  Side effects:
  379.  *    This routine will cause a core dump if the allocation requests fail.
  380.  *
  381.  *  Results:
  382.  *    SUCCESS     The default server was changed successfully.
  383.  *    NONAUTH        The server was changed but addresses of
  384.  *            other servers who know about the requested server
  385.  *            were returned.
  386.  *    Errors        No info about the new server was found or
  387.  *            requests to the current server timed-out.
  388.  *
  389.  *******************************************************************************
  390.  */
  391.  
  392. int
  393. SetDefaultServer(string, local)
  394.     char    *string;
  395.     Boolean    local;
  396. {
  397.     register HostInfo     *newDefPtr;
  398.     char         newServer[NAME_LEN];
  399.     int         result;
  400.     int         i;
  401.  
  402.     /*
  403.      *  Parse the command line. It maybe of the form "server name",
  404.      *  "lserver name" or just "name".
  405.      */
  406.  
  407.     if (local) {
  408.     i = sscanf(string, " lserver %s", newServer);
  409.     } else {
  410.     i = sscanf(string, " server %s", newServer);
  411.     }
  412.     if (i != 1) {
  413.     i = sscanf(string, " %s", newServer);
  414.     if (i != 1) {
  415.         fprintf(stderr,"SetDefaultServer: invalid name: %s\n",  string);
  416.         return(ERROR);
  417.     }
  418.     }
  419.  
  420.     /*
  421.      * Allocate space for a HostInfo variable for the new server. Don't
  422.      * overwrite the old HostInfo struct because info about the new server
  423.      * might not be found and we need to have valid default server info.
  424.      */
  425.  
  426.     newDefPtr = (HostInfo *) Calloc(1, sizeof(HostInfo));
  427.  
  428.  
  429.     /*
  430.      *    A 'local' lookup uses the original server that the program was
  431.      *  initialized with.
  432.      */
  433.  
  434.     if (local) {
  435.     result = GetHostInfo(&defaultAddr, C_IN, T_A, newServer, newDefPtr, 1);
  436.     } else {
  437.  
  438.     /*
  439.      *  Check to see if we have the address of the server or the
  440.      *    address of a server who knows about this domain.
  441.      *
  442.      *  For now, just use the first address in the list.
  443.      */
  444.     if (defaultPtr->addrList == NULL) {
  445.         result = GetHostInfo(
  446.             (struct in_addr *) defaultPtr->servers[0]->addrList[0], 
  447.                 C_IN, T_A, newServer, newDefPtr, 1);
  448.     } else {
  449.         result = GetHostInfo((struct in_addr *) defaultPtr->addrList[0], 
  450.                 C_IN, T_A, newServer, newDefPtr, 1);
  451.     }
  452.     }
  453.  
  454.     if (result == SUCCESS || result == NONAUTH) {
  455.         /*
  456.          *  Found info about the new server. Free the resources for
  457.          *  the old server.
  458.          */
  459.  
  460.         FreeHostInfoPtr(defaultPtr);
  461.         free((char *)defaultPtr);
  462.         defaultPtr = newDefPtr;
  463.         strcpy(defaultServer, defaultPtr->name);
  464.         PrintHostInfo(stdout, "Default Server:", defaultPtr);
  465.         return(SUCCESS);
  466.     } else {
  467.         fprintf(stderr, "*** Can't find address for server %s: %s\n",
  468.             newServer, DecodeError(result));
  469.         free((char *)newDefPtr);
  470.  
  471.         return(result);
  472.     }
  473. }
  474.  
  475. /*
  476.  *******************************************************************************
  477.  *
  478.  *  LookupHost --
  479.  *
  480.  *    Asks the default name server for information about the
  481.  *    specified host or domain. The information is printed
  482.  *    if the lookup was successful.
  483.  *
  484.  *  Results:
  485.  *    SUCCESS        - the lookup was successful.
  486.  *    ERROR        - the output file could not be opened.
  487.  *    Misc. Errors    - an error message is printed if the lookup failed.
  488.  *
  489.  *******************************************************************************
  490.  */
  491.  
  492. int
  493. LookupHost(string, putToFile)
  494.     char    *string;
  495.     Boolean    putToFile;
  496. {
  497.     char    host[NAME_LEN];
  498.     char    file[NAME_LEN];
  499.     int        result;
  500.  
  501.     /*
  502.      *  Invalidate the current host information to prevent Finger 
  503.      *  from using bogus info.
  504.      */
  505.  
  506.     curHostValid = FALSE;
  507.  
  508.     /*
  509.      *     Parse the command string into the host and
  510.      *     optional output file name.
  511.      *
  512.      */
  513.  
  514.     sscanf(string, " %s", host);    /* removes white space */
  515.     if (!putToFile) {
  516.     filePtr = stdout;
  517.     } else {
  518.     filePtr = OpenFile(string, file);
  519.     if (filePtr == NULL) {
  520.         fprintf(stderr, "*** Can't open %s for writing\n", file);
  521.         return(ERROR);
  522.     }
  523.     fprintf(filePtr,"> %s\n", string);
  524.     }
  525.  
  526.     PrintHostInfo(filePtr, "Server:", defaultPtr);
  527.  
  528.     /*
  529.      *  Check to see if we have the address of the server or the
  530.      *    address of a server who knows about this domain.
  531.      *
  532.      *  For now, just use the first address in the list.
  533.      */
  534.  
  535.     if (defaultPtr->addrList == NULL) {
  536.     result = GetHostInfo(
  537.             (struct in_addr *) defaultPtr->servers[0]->addrList[0], 
  538.               queryClass, queryType, host, &curHostInfo, 0);
  539.     } else {
  540.     result = GetHostInfo((struct in_addr *) defaultPtr->addrList[0], 
  541.               queryClass, queryType, host, &curHostInfo, 0);
  542.     }
  543.  
  544.     switch(result) {
  545.     case SUCCESS:
  546.         /*
  547.          *  If the query was for an address, then the curHostInfo
  548.          *  variable can be used by Finger.
  549.          *  There's no need to print anything for other query types
  550.          *  because the info has already been printed.
  551.          */
  552.         if (queryType == T_A) {
  553.         curHostValid = TRUE;
  554.         PrintHostInfo(filePtr, "Name:", &curHostInfo);
  555.         }
  556.         break;
  557.  
  558.     /*
  559.      * No Authoritative answer was available but we got names
  560.      * of servers who know about the host.
  561.      */
  562.     case NONAUTH:
  563.         PrintHostInfo(filePtr, "Name:", &curHostInfo);
  564.         break;
  565.  
  566.     case NO_INFO:
  567.         fprintf(stderr, "*** No %s information is available for %s\n", 
  568.             DecodeType(queryType), host);
  569.         break;
  570.  
  571.     case TIME_OUT:
  572.         fprintf(stderr, "*** Request to %s timed-out\n", defaultServer);
  573.         break;
  574.  
  575.     default:
  576.         fprintf(stderr, "*** %s can't find %s: %s\n", defaultServer, host,
  577.             DecodeError(result));
  578.     }
  579.     if (putToFile) {
  580.     fclose(filePtr);
  581.     filePtr = NULL;
  582.     }
  583.     return(result);
  584. }
  585.  
  586. /*
  587.  *******************************************************************************
  588.  *
  589.  *  LookupHostWithServer --
  590.  *
  591.  *    Asks the name server specified in the second argument for 
  592.  *    information about the host or domain specified in the first
  593.  *    argument. The information is printed if the lookup was successful.
  594.  *
  595.  *    Address info about the requested name server is obtained
  596.  *    from the default name server. This routine will return an
  597.  *    error if the default server doesn't have info about the 
  598.  *    requested server. Thus an error return status might not
  599.  *    mean the requested name server doesn't have info about the
  600.  *    requested host.
  601.  *
  602.  *    Comments from LookupHost apply here, too.
  603.  *
  604.  *  Results:
  605.  *    SUCCESS        - the lookup was successful.
  606.  *    ERROR        - the output file could not be opened.
  607.  *    Misc. Errors    - an error message is printed if the lookup failed.
  608.  *
  609.  *******************************************************************************
  610.  */
  611.  
  612. int
  613. LookupHostWithServer(string, putToFile)
  614.     char    *string;
  615.     Boolean    putToFile;
  616. {
  617.     char     file[NAME_LEN];
  618.     char     host[NAME_LEN];
  619.     char     server[NAME_LEN];
  620.     int     result;
  621.     static HostInfo serverInfo;
  622.  
  623.     curHostValid = FALSE;
  624.  
  625.     sscanf(string, " %s %s", host, server);
  626.     if (!putToFile) {
  627.     filePtr = stdout;
  628.     } else {
  629.     filePtr = OpenFile(string, file);
  630.     if (filePtr == NULL) {
  631.         fprintf(stderr, "*** Can't open %s for writing\n", file);
  632.         return(ERROR);
  633.     }
  634.     fprintf(filePtr,"> %s\n", string);
  635.     }
  636.     
  637.  
  638.     if (defaultPtr->addrList == NULL) {
  639.     result = GetHostInfo(
  640.             (struct in_addr *) defaultPtr->servers[0]->addrList[0], 
  641.                 C_IN, T_A, server, &serverInfo, 1);
  642.     } else {
  643.     result = GetHostInfo((struct in_addr *) defaultPtr->addrList[0], 
  644.                 C_IN, T_A, server, &serverInfo, 1);
  645.     }
  646.  
  647.     if (result != SUCCESS) {
  648.     fprintf(stderr,"*** Can't find address for server %s: %s\n", server,
  649.          DecodeError(result));
  650.     } else {
  651.     PrintHostInfo(filePtr, "Server:", &serverInfo);
  652.  
  653.     if (serverInfo.addrList == NULL) {
  654.         result = GetHostInfo(
  655.             (struct in_addr *) serverInfo.servers[0]->addrList[0], 
  656.                   queryClass, queryType, host, &curHostInfo, 0);
  657.     } else {
  658.         result = GetHostInfo((struct in_addr *) serverInfo.addrList[0], 
  659.                   queryClass, queryType, host, &curHostInfo, 0);
  660.     }
  661.  
  662.  
  663.     switch(result) {
  664.  
  665.         case SUCCESS:
  666.         if (queryType == T_A) {
  667.             curHostValid = TRUE;
  668.             PrintHostInfo(filePtr, "Name:", &curHostInfo);
  669.         }
  670.         break;
  671.  
  672.         case NONAUTH:
  673.         PrintHostInfo(filePtr, "Name:", &curHostInfo);
  674.         break;
  675.  
  676.         case NO_INFO:
  677.         fprintf(stderr, "*** No %s information is available for %s\n", 
  678.             DecodeType(queryType), host);
  679.         break;
  680.  
  681.         case TIME_OUT:
  682.         fprintf(stderr, "*** Request to %s timed-out\n", server);
  683.         break;
  684.  
  685.         default:
  686.         fprintf(stderr, "*** %s can't find %s: %s\n", server, host,
  687.             DecodeError(result));
  688.     }
  689.     }
  690.     if (putToFile) {
  691.     fclose(filePtr);
  692.     filePtr = NULL;
  693.     }
  694.     return(result);
  695. }
  696.  
  697. /*
  698.  *******************************************************************************
  699.  *
  700.  *  SetOption -- 
  701.  *
  702.  *    This routine is used to change the state information
  703.  *    that affect the lookups. The command format is
  704.  *       set keyword[=value]
  705.  *    Most keywords can be abbreviated. Parsing is very simplistic--
  706.  *    A value must not be separated from its keyword by white space.
  707.  *
  708.  *    Valid keywords:        Meaning:
  709.  *    [no]aaonly          authoritative query only or not (hidden).
  710.  *    all            lists current values of options.
  711.  *    ALL            lists current values of options, including
  712.  *                  hidden options.
  713.  *    [no]d2            turn on/off extra debugging mode (hidden).
  714.  *    [no]debug         turn on/off debugging mode.
  715.  *    [no]defname          use/don't use default domain name.
  716.  *    [no]search        use/don't use domain search list.
  717.  *    domain=NAME        set default domain name to NAME.
  718.  *    [no]ignore        ignore/don't ignore trunc. errors (hidden).
  719.  *    [no]primary         use/don't use primary server (hidden).
  720.  *    query=value        set default query type to value,
  721.  *                value is one of the query types in RFC883
  722.  *                without the leading T_.    (e.g. A, HINFO)
  723.  *    [no]recurse        use/don't use recursive lookup.
  724.  *    retry=#            set number of retries to #.
  725.  *    root=NAME        change root server to NAME.
  726.  *    time=#            set timeout length to #.
  727.  *    [no]vc            use/don't use virtual circuit.
  728.  *
  729.  *  Results:
  730.  *    SUCCESS        the command was parsed correctly.
  731.  *    ERROR        the command was not parsed correctly.
  732.  *
  733.  *******************************************************************************
  734.  */
  735.  
  736. int
  737. SetOption(option)
  738.     register char *option;
  739. {
  740.     char     type[NAME_LEN];
  741.     char     *ptr;
  742.  
  743.     while (isspace(*option))
  744.     ++option;
  745.     if (strncmp (option, "set ", 4) == 0)
  746.     option += 4;
  747.     while (isspace(*option))
  748.     ++option;
  749.  
  750.     if (*option == 0) {
  751.     fprintf(stderr, "*** Invalid set command\n");
  752.     return(ERROR);
  753.     } else {
  754.     if (strncmp(option, "all", 3) == 0) {
  755.         ShowOptions(FALSE);
  756.     } else if (strncmp(option, "ALL", 3) == 0) {
  757.         ShowOptions(TRUE);
  758.     } else if (strncmp(option, "aa", 2) == 0) {    /* aaonly */
  759.         _res.options |= RES_AAONLY;
  760.     } else if (strncmp(option, "noaa", 4) == 0) {
  761.         _res.options &= ~RES_AAONLY;
  762.     } else if (strncmp(option, "d2", 2) == 0) {    /* d2 (more debug) */
  763.         _res.options |= (RES_DEBUG | RES_DEBUG2);
  764.     } else if (strncmp(option, "nod2", 4) == 0) {
  765.         _res.options &= ~RES_DEBUG2;
  766.     } else if (strncmp(option, "def", 3) == 0) {    /* defname */
  767.         _res.options |= RES_DEFNAMES;
  768.     } else if (strncmp(option, "nodef", 5) == 0) {
  769.         _res.options &= ~RES_DEFNAMES;
  770.     } else if (strncmp(option, "do", 2) == 0) {    /* domain */
  771.         ptr = index(option, '=');
  772.         if (ptr != NULL) {
  773.         sscanf(++ptr, "%s", _res.defdname);
  774.         res_re_init();
  775.         }
  776.     } else if (strncmp(option, "deb", 1) == 0) {    /* debug */
  777.         _res.options |= RES_DEBUG;
  778.     } else if (strncmp(option, "nodeb", 3) == 0) {
  779.         _res.options &= ~(RES_DEBUG | RES_DEBUG2);
  780.     } else if (strncmp(option, "i", 1) == 0) {    /* ignore */
  781.         _res.options |= RES_IGNTC;
  782.     } else if (strncmp(option, "noi", 3) == 0) {
  783.         _res.options &= ~RES_IGNTC;
  784.     } else if (strncmp(option, "p", 1) == 0) {    /* primary */
  785.         _res.options |= RES_PRIMARY;
  786.     } else if (strncmp(option, "nop", 3) == 0) {
  787.         _res.options &= ~RES_PRIMARY;
  788.     } else if (strncmp(option, "q", 1) == 0 ||    /* querytype */
  789.       strncmp(option, "ty", 2) == 0) {
  790.         ptr = index(option, '=');
  791.         if (ptr != NULL) {
  792.         sscanf(++ptr, "%s", type);
  793.         queryType = StringToType(type, queryType);
  794.         }
  795.     } else if (strncmp(option, "cl", 2) == 0) {    /* query class */
  796.         ptr = index(option, '=');
  797.         if (ptr != NULL) {
  798.         sscanf(++ptr, "%s", type);
  799.         queryClass = StringToClass(type, queryClass);
  800.         }
  801.     } else if (strncmp(option, "rec", 3) == 0) {    /* recurse */
  802.         _res.options |= RES_RECURSE;
  803.     } else if (strncmp(option, "norec", 5) == 0) {
  804.         _res.options &= ~RES_RECURSE;
  805.     } else if (strncmp(option, "ret", 3) == 0) {    /* retry */
  806.         ptr = index(option, '=');
  807.         if (ptr != NULL) {
  808.         sscanf(++ptr, "%d", &_res.retry);
  809.         }
  810.     } else if (strncmp(option, "ro", 2) == 0) {    /* root */
  811.         ptr = index(option, '=');
  812.         if (ptr != NULL) {
  813.         sscanf(++ptr, "%s", rootServerName);
  814.         }
  815.     } else if (strncmp(option, "sea", 3) == 0) {    /* search list */
  816.         _res.options |= RES_DNSRCH;
  817.     } else if (strncmp(option, "nosea", 5) == 0) {
  818.         _res.options &= ~RES_DNSRCH;
  819.     } else if (strncmp(option, "t", 1) == 0) {    /* timeout */
  820.         ptr = index(option, '=');
  821.         if (ptr != NULL) {
  822.         sscanf(++ptr, "%d", &_res.retrans);
  823.         }
  824.     } else if (strncmp(option, "v", 1) == 0) {    /* vc */
  825.         _res.options |= RES_USEVC;
  826.     } else if (strncmp(option, "nov", 3) == 0) {
  827.         _res.options &= ~RES_USEVC;
  828.     } else {
  829.         fprintf(stderr, "*** Invalid option: %s\n",  option);
  830.         return(ERROR);
  831.     }
  832.     }
  833.     return(SUCCESS);
  834. }
  835.  
  836. /*
  837.  * Fake a reinitialization when the domain is changed.
  838.  */
  839. res_re_init()
  840. {
  841.     register char *cp, **pp;
  842.     int n;
  843.  
  844.     /* find components of local domain that might be searched */
  845.     pp = _res.dnsrch;
  846.     *pp++ = _res.defdname;
  847.     for (cp = _res.defdname, n = 0; *cp; cp++)
  848.     if (*cp == '.')
  849.         n++;
  850.     cp = _res.defdname;
  851.     for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDNSRCH; n--) {
  852.     cp = index(cp, '.');
  853.     *pp++ = ++cp;
  854.     }
  855.     *pp = 0;
  856.     _res.options |= RES_INIT;
  857. }
  858.  
  859. /*
  860.  *******************************************************************************
  861.  *
  862.  *  ShowOptions --
  863.  *
  864.  *    Prints out the state information used by the resolver
  865.  *    library and other options set by the user.
  866.  *
  867.  *******************************************************************************
  868.  */
  869.  
  870. void
  871. ShowOptions(special)
  872.     int special;
  873. {
  874.     int i;
  875.     register char **cp;
  876.  
  877.     PrintHostInfo(stdout, "Default Server:", defaultPtr);
  878.     if (curHostValid) {
  879.     PrintHostInfo(stdout, "Host:", &curHostInfo);
  880.     }
  881.  
  882.     printf("Set options:\n");
  883.     printf("  %sdebug  \t", (_res.options & RES_DEBUG) ? "" : "no");
  884.     printf("  %sdefname\t", (_res.options & RES_DEFNAMES) ? "" : "no");
  885.     printf("  %ssearch\t", (_res.options & RES_DNSRCH) ? "" : "no");
  886.     printf("  %srecurse\t", (_res.options & RES_RECURSE) ? "" : "no");
  887.     printf("  %svc\n", (_res.options & RES_USEVC) ? "" : "no");
  888.  
  889.     if (special) {
  890.     printf("  %saa\t\t", (_res.options & RES_AAONLY) ? "" : "no");
  891.     printf("  %sd2\t\t", (_res.options & RES_DEBUG2) ? "" : "no");
  892.     printf("  %signoretc\t", (_res.options & RES_IGNTC) ? "" : "no");
  893.     printf("  %sprimary\n", (_res.options & RES_PRIMARY) ? "" : "no");
  894.     }
  895.  
  896.     printf("  querytype=%s\t", p_type(queryType));
  897.     printf("  class=%s\t", p_class(queryClass));
  898.     printf("  timeout=%d\t", _res.retrans);
  899.     printf("  retry=%d\n", _res.retry);
  900.     printf("  domain=%s\n", _res.defdname);
  901.     printf("  search list: ");
  902.     for (cp = _res.dnsrch; *cp; cp++)
  903.     printf("%s ", *cp);
  904.     printf("\n  root=%s\n", rootServerName);
  905.  
  906.     if (special) {
  907.     printf("\n");
  908.     printf("State info:\n");
  909.     printf("  current packet id:       %d\n", (int)_res.id);
  910.     printf("  number of name servers:  %d\n", _res.nscount);
  911.     printf("  name server addresses:   %s\n",
  912.                     inet_ntoa(_res.nsaddr_list[0].sin_addr));
  913.     for (i = 1; i < _res.nscount; i++) {
  914.         printf("                           %s\n", 
  915.             inet_ntoa(_res.nsaddr_list[i].sin_addr));
  916.     }
  917.     }
  918. }
  919.  
  920. /*
  921.  *******************************************************************************
  922.  *
  923.  *  PrintHelp --
  924.  *
  925.  *    Prints out the help file.
  926. *    (Code taken from Mail.)
  927.  *
  928.  *******************************************************************************
  929.  */
  930.  
  931. void
  932. PrintHelp()
  933. {
  934.     register int c;
  935.     register FILE *helpFilePtr;
  936.  
  937.     if ((helpFilePtr = fopen(HELPFILE, "r")) == NULL) {
  938.         perror(HELPFILE);
  939.         return;
  940.     } 
  941.     while ((c = getc(helpFilePtr)) != EOF) {
  942.         putchar((char) c);
  943.     }
  944.     fclose(helpFilePtr);
  945. }
  946.